package jcommon.chap3_bean;

import java.util.Arrays;
import java.util.Comparator;

import jcommon.beans4ex.Athlete;
import jcommon.beans4ex.Person;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.apache.commons.collections.comparators.FixedOrderComparator;
import org.apache.commons.collections.comparators.NullComparator;
import org.apache.commons.lang.ArrayUtils;

public class Comparing {
	public static void main(String[] args) {

		// BeanComparator( String property, Comparator comparator )
		// 实际上是个装饰器。若指定了property和comparator，则会取Bean的property值再用
		// comparator比较
		System.out.println("-------- Test BeanComparator --------");
		testBeanComparator();

		System.out.println("-------- Test NullComparator --------");
		comparingNullBean();

		System.out.println("-------- CompareNullProperty --------");
		compareNullProperty();
		
		System.out.println("-------- Test FiexedOrderedComparator --------");
		fixOrder();
		
		System.out.println("-------- Test ChainComparator --------");
		chainComparatorDemo();

		System.out.println("-------- Test FilterComparator --------");
		testComposedComparator();
		/*
		 * Use FixedOrderComparator when sorting an array or a collection that
		 * contains values that are ordered in a pre-determined fashion: days of
		 * the week, planets in the solar system, colors in the spectrum, or
		 * hands dealt in a poker game.
		 */
	}

	public static void testBeanComparator() {
		// -- 准备数据 --
		Person person1 = new Person();
		person1.setName("Petter");
		Person person2 = new Person();
		person2.setName("Sylar");
		Person person3 = new Person();
		person3.setName("Matt");
		Person[] persons = new Person[] { person1, person2, person3 };

		Comparator nameCompare = new BeanComparator("name");

		System.out.println(ArrayUtils.toString(persons));
		Arrays.sort(persons, nameCompare);
		System.out.println(ArrayUtils.toString(persons));
	}

	public static void comparingNullBean() {
		// -- 准备数据，多个null --
		Person person1 = new Person();
		person1.setName("Petter");
		Person person2 = new Person();
		person2.setName("Sylar");
		Person person3 = new Person();
		person3.setName("Matt");
		Person[] persons = new Person[] { person1, null, person2, person3 }; // 多了个null

		Comparator nameCompare = new BeanComparator("name");
		// 由于name可能为null，所以得这样：
		Comparator nullComparator = new NullComparator(nameCompare);

		System.out.println(ArrayUtils.toString(persons));
		Arrays.sort(persons, nullComparator);
		System.out.println(ArrayUtils.toString(persons));
	}

	private static void compareNullProperty() {
		// -- 准备数据 --
		Person person1 = new Person();
		person1.setName("Petter");
		Person person2 = new Person(); // name为null
		Person person3 = new Person();
		Person[] persons = new Person[] { person1, person2, person3 };

		// BeanComparator 默认使用的 ComparableComparator没有防止npe，所以前面给它加上个
		// NullComparator
		Comparator nameCompare = new BeanComparator("name", new NullComparator(
				ComparableComparator.getInstance()));

		System.out.println(ArrayUtils.toString(persons));
		Arrays.sort(persons, nameCompare);
		System.out.println(ArrayUtils.toString(persons));
	}


	private static void fixOrder() {
		String[] order = {"1", "2", "3", "6", "8"};
		FixedOrderComparator orderComparator = new FixedOrderComparator(order);
		// orderComparator.setUnknownObjectBehavior(FixedOrderComparator.UNKNOWN_AFTER);
		
		String[] unordered = {"6", "8", "5", "1", "3", "2"};
		
		System.out.println(ArrayUtils.toString(unordered));
		Arrays.sort(unordered, orderComparator);
		System.out.println(ArrayUtils.toString(unordered));
	}

	/*
	 * A ComparatorChain evaluates every Comparator in the chain as needed. If
	 * the current Comparator returns a zero, the next Comparator is invoked
	 * until there are no more Comparator objects left in the chain. If the
	 * final Comparator returns a zero value, the ComparatorChain returns a
	 * zero.
	 */
	private static void chainComparatorDemo() {
		Person person1 = new Person();
		person1.setName("Petter");
		person1.setAge(26);
		Person person2 = new Person();
		person2.setName("Sylar");
		person2.setAge(28);
		Person person3 = new Person();
		person3.setName("Sylar");
		person3.setAge(55);
		Person person4 = new Person();
		person4.setName("matt");
		person4.setAge(38);
		Person[] persons = new Person[] { person1, person2, person3, person4 };

		ComparatorChain cc = new ComparatorChain();
		cc.addComparator(new BeanComparator("name"));
		cc.addComparator(new BeanComparator("age"), true);

		System.out.println(ArrayUtils.toString(persons));
		Arrays.sort(persons, cc);
		System.out.println(ArrayUtils.toString(persons));
	}

	public static void testComposedComparator() {
		String[] medalOrder = { "tin", "bronze", "silver", "gold", "platinum" };
		Comparator medalComparator = new FixedOrderComparator(medalOrder);
		Comparator athleteComparator = new BeanComparator("medal",
				medalComparator);

		Athlete athlete1 = new Athlete();
		athlete1.setMedal("platinum");
		Athlete athlete2 = new Athlete();
		athlete2.setMedal("gold");
		Athlete athlete3 = new Athlete();
		athlete3.setMedal("bronze");
		Athlete athlete4 = new Athlete();
		athlete4.setMedal("tin");
		
		Athlete[] athletes = new Athlete[]{athlete1, athlete2, athlete3, athlete4};
		
		System.out.println(ArrayUtils.toString(athletes));
		Arrays.sort(athletes, athleteComparator);
		System.out.println(ArrayUtils.toString(athletes));
	}
}
